package com.ms.aspectj.param;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @Aspect 使用除了要添加这个注解之外还需要添加@Component注解
* @Author ztd
*/
@Aspect
@Component
@Slf4j
public class AspectjAdviceWithParam {
    @Pointcut("execution(public * * (..)) && args(i,j,..)")
    public void pointCut(int i, int j) {

    }

    /**
     *  在目标方法之前切入；切入点表达式（指定在哪个方法切入）
     * @param joinPoint
     * @param i
     * @param j
     */
    @Before(value = "pointCut(i,j)", argNames = "joinPoint, i, j")
    public void logStart(JoinPoint joinPoint, int i, int j){
        log.info("====@Before====");
        log.info("@Before 执行参数:i->{}, j->{}", i, j);
        log.info("@Before method name:{}", joinPoint.getSignature().getName());
        log.info("@Before args:{}", Arrays.asList(joinPoint.getArgs()));
    }

    @Around(value = "pointCut(i,j)", argNames = "joinPoint, i, j")
    public Object logAround(ProceedingJoinPoint joinPoint, int i, int j) throws Throwable {
        log.info("====@Around-start====");
        log.info("@Around method name:{}", joinPoint.getSignature().getName());
        Object result = joinPoint.proceed();
        log.info("====@Around-end====");
        return result;
    }

    @After(value = "pointCut(i,j)", argNames = "joinPoint, i, j")
    public void logEnd(JoinPoint joinPoint, int i, int j){
        log.info("====@After====");
        log.info("@After method name:->{}", joinPoint.getSignature().getName());
    }

    /**
     * JoinPoint一定要出现在参数表的第一位
     * @param joinPoint
     * @param result
     * @param i
     * @param j
     */
    @AfterReturning(value="pointCut(i,j)", argNames = "joinPoint, result, i, j",returning="result")
    public void logReturn(JoinPoint joinPoint, Object result, int i, int j){
        log.info("====@AfterReturning====");
        log.info("@AfterReturning method name:->{}", joinPoint.getSignature().getName());
        log.info("@AfterReturning result:{}", result);
    }

    @AfterThrowing(value="pointCut(i, j)", argNames = "joinPoint, i, j, exception", throwing="exception")
    public void logException(JoinPoint joinPoint,int i, int j, Exception exception){
        log.info("@AfterThrowing method name:->{}", joinPoint.getSignature().getName());
        if (exception instanceof MyException) {
            log.info("报MyException错误了:{}", exception);
        } else if(exception instanceof ArithmeticException) {
            log.info("报ArithmeticException错误了:{}", exception);
        }
    }

}
